// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

`timescale 1ns / 1ps

module blocking_reset_flow
(
    input  iClk,
    input  iRst_n,
    input  iMCERR,          // CATERR_ENCODE [0]
    input  iIERR,           // CATERR_ENCODE [1]
	input  iPLTRST_N,
	input  iGLBRST_N,
	input  iAsync_GLBRST,  
	input  iAsync_WarmR,    
	input  iPwrBtn_N,       
	input  iRstBtn_N,       
	
	output oPLTRST_N,
	output oGLBRST_N,
	output oAsync_GLBRST,
    output oAsync_WarmR
    
);

/*************************************************************************************************************
 * Local Parameter Definitions                                                                               *
 *************************************************************************************************************/
   localparam  LOW                 = 1'b0;
   localparam  HIGH                = 1'b1;
   localparam  TRISTATE            = 1'bZ;

    localparam  ST_INIT               = 4'd0;
	 localparam  ST_BMC_COMPLETION_MCERR  = 4'd1;
	 localparam  ST_BMC_COMPLETION_IERR   = 4'd2;
	 localparam  ST_STOP_BLOCKING         = 4'd3;
	 localparam  ST_GLBRST                = 4'd4;
	 localparam  ST_MCERR_DEASSERTION     = 4'd5;
	 localparam  ST_IERR_DEASSERTION      = 4'd6;	

/*************************************************************************************************************
 * Local Registers and Wires Definitions                                                                     *
 *************************************************************************************************************/

   reg [3:0] rstate;
   reg       rPLTRST_N;
   reg       rGLBRST_N;
   reg       rAsync_GLBRST;
   reg       rAsync_WarmR;
	reg       rIerr_latch;

/*************************************************************************************************************
 * Logic                                                                                                     *
 *************************************************************************************************************/

    always @ (posedge iClk or negedge iRst_n) begin
        if (!iRst_n) begin
           rstate         <= ST_INIT;
		   rPLTRST_N      <= LOW;
		   rGLBRST_N      <= LOW;
		   rAsync_GLBRST  <= LOW;
		   rAsync_WarmR   <= LOW;
			rIerr_latch    <= LOW;
 
        end
        else begin
			case (rstate)
                ST_INIT: begin
				    if( iMCERR ) begin  // If there is CATERR (mcerr case) start blocking all the reset petitions and go to wait for BMC completion
		                rPLTRST_N            <= HIGH;
		                rGLBRST_N            <= HIGH;
		                rAsync_GLBRST        <= LOW;
		                rAsync_WarmR         <= LOW;
						 rIerr_latch          <= LOW;
						 rstate               <= ST_BMC_COMPLETION_MCERR; // jump to next state
					 end else if (iIERR) begin   // If there is CATERR asserted (ierr case) start blocking all the reset petitions and go to wait for BMC completion
		                rPLTRST_N            <= HIGH;
		                rGLBRST_N            <= HIGH;
		                rAsync_GLBRST        <= LOW;
		                rAsync_WarmR         <= LOW;
						 rstate               <= ST_BMC_COMPLETION_IERR; // jump to next state
                    end else begin           // If there is no CATERR asserted allow all the reset petitions
					    rPLTRST_N            <= iPLTRST_N;
		                rAsync_WarmR         <= iAsync_WarmR;
				        rAsync_GLBRST        <= iAsync_GLBRST;
				        rGLBRST_N            <= iGLBRST_N;
					    rstate               <= ST_INIT;
						end
					end //case INIT

				 ST_BMC_COMPLETION_MCERR: begin
		            rPLTRST_N      <= HIGH;  // Keep blocking all reset petitions
		            rGLBRST_N      <= HIGH;
				    rAsync_GLBRST  <= LOW;
		            rAsync_WarmR   <= LOW;
					 if (iAsync_WarmR | !iPwrBtn_N | !iRstBtn_N) begin       // if BMC_Completion is asserted jump to ST_STOP_BLOCKING
						 rstate       <=  ST_MCERR_DEASSERTION;                              /// rstate       <= ST_STOP_BLOCKING;
					 end else begin
						 rstate       <= ST_BMC_COMPLETION_MCERR;   
					   end
					end //case ST_CLIP_DEASSERTED
					
					 ST_BMC_COMPLETION_IERR: begin
						 rIerr_latch    <= HIGH;
						 rPLTRST_N      <= HIGH;  // Keep blocking all reset petitions
		                rGLBRST_N         <= HIGH;
		                rAsync_GLBRST     <= LOW;
		                rAsync_WarmR      <= LOW;
						 if (iAsync_WarmR || !iPwrBtn_N || !iRstBtn_N) begin       // if BMC_Completion is asserted jump to ST_STOP_BLOCKING
							 rstate       <= ST_STOP_BLOCKING;                              
							end
							else begin
							 rstate       <= ST_BMC_COMPLETION_IERR;   
						 end
						 end //case ST_CLIP_DEASSERTED
				 ST_STOP_BLOCKING: begin
					  if (!iGLBRST_N) begin // There is GLBRST PETITION
						  rGLBRST_N     <= iGLBRST_N;
						  rstate       <= ST_IERR_DEASSERTION ; 
					 end else if ((!iPLTRST_N)  ) begin // There is PLTRST PETITION
						  rPLTRST_N     <= iPLTRST_N;
						  rstate       <=ST_IERR_DEASSERTION ; 
					 end else if (iPLTRST_N & (rIerr_latch )) begin // There is no PLTRST PETITION and we are in the IERR flow
						 rAsync_WarmR  <= HIGH;   // Trigger the Async_WarmR for IERR case and go to wait for CATERR deassertion
						  rstate       <= ST_IERR_DEASSERTION  ;
				    end
					 else begin 
						 rstate       <= ST_STOP_BLOCKING; 
					 end
				end // case ST_STOP_BLOCKING
				
				 ST_IERR_DEASSERTION : begin
					 if (!iIERR) begin       // if iIERR is deasserted jump to ST_INIT
					   rstate       <= ST_INIT;
					 end else begin
						 rstate       <= ST_IERR_DEASSERTION ;	
					   end
 
					end 
				
					ST_MCERR_DEASSERTION: begin
			  
					 if (!iMCERR & !iAsync_WarmR ) begin       // if !iMCERR is deasserted jump to ST_INIT
						 rstate       <= ST_INIT;
					 end else begin
						 rstate       <= ST_MCERR_DEASSERTION;	
 
					 end
 
					end 
				
				default: begin
                    rstate              <= ST_INIT;
                    end // case: default
                endcase
		end //else
	end // always
						
assign oPLTRST_N     = rPLTRST_N;
assign oGLBRST_N     = rGLBRST_N;
assign oAsync_GLBRST = rAsync_GLBRST;
assign oAsync_WarmR  = rAsync_WarmR;

 
endmodule	
